#pragma once 
#include<functional>
#include<signal.h>
#include"Socket.hpp"

//使用说明：
//TcpServer server(port,callback);
//server.Start();

using func = std::function<std::string(std::string &package)>;

class TcpServer
{
    private:
        Sock _listensock;
        func _callback;   //子进程的数据处理函数
    public:
        TcpServer(uint16_t port,func callback):_callback(callback)
        {
            _listensock.Socket();
            _listensock.Bind(port);
            _listensock.Listen();
            lg(Info, "init server .... done");
        }

        //不停的拉客，拉来的客人交给子进程去处理
        //子进程：读取数据，将读取来的数据交给处理函数处理，返回处理结果，将处理结果打包发送给客户端，一直循环，直到该客户端退出
        void Start()   
        {
            //原本：当子进程终止时，内核会向父进程发送此SIGCHLD 信号，父进程去回收子进程（调用 wait/waitpid）。如果不调用的话，父进程成为了僵尸进程
            //SIGCHLD 信号改成SIG_IGN 后，内核会 立即清理子进程资源，父进程无需手动调用 wait。防止父进程成为僵尸进程
            signal(SIGCHLD,SIG_IGN); 
            //SIGPIPE 信号：当进程向一个已关闭的套接字（或管道）写入数据时，内核会发送此信号（默认行为是终止进程）。
            //忽略 SIGPIPE 信号，防止向已关闭的套接字写入数据时进程被终止。
            //场景：在网络编程中，客户端可能突然断开连接，但服务器可能尚未感知（例如正在调用 write()） 
            signal(SIGPIPE,SIG_IGN);

            while(true)
            {
                //拉客
                std::string clientip;
                uint16_t clientport;
                int sockfd=_listensock.Accept(&clientip,&clientport);  //拉客没成功，会阻塞
                if (sockfd < 0)
                    continue;

                lg(Info, "accept a new link, sockfd: %d, clientip: %s, clientport: %d", sockfd, clientip.c_str(), clientport);

                if(fork()==0)  //子进程
                {
                    close(_listensock.Fd());  //子进程关闭监听套接字
                    std::string inbuffer_stream;   //必须放在while外面,可以把不完整的请求连接起来，形成完整请求
                    while(true)
                    {
                        // 读数据
                        char buffer[1024];
                        int n = read(sockfd, buffer, sizeof(buffer));
                        if (n > 0)
                        {
                            buffer[n]='\0';
                            inbuffer_stream+=buffer;
                            lg(Debug, "Request11111111111:\n%s", inbuffer_stream.c_str());  //显示所有的请求，可能有多个或者半个

                            //加 while(true) 是为了处理多条请求
                            while (true)
                            {
                                // 处理数据
                                std::string info = _callback(inbuffer_stream); //_callback 处理请求时必须修改 inbuffer_stream
                                if(info.empty())  //可能请求不完整
                                    break;
                                lg(Debug,"Response2222222222222:\n%s",info.c_str());    //显示出响应
                                lg(Debug, "debug333333333333:\n%s", inbuffer_stream.c_str());  //显示剩余的请求
                                // 发送数据给客户端
                                write(sockfd, info.c_str(), info.size());
                            }
                        }
                        else if (n == 0)
                        {
                            std::cout << "Clinet Quit\n";
                            break;
                        }
                        else if (n < 0)
                        {
                            lg(Fatal,"read error");
                            break;
                        }
                    }
                    close(sockfd);
                    exit(0);  //子进程退出
                }
                close(sockfd);    //父进程关闭连接套接字
            }
            _listensock.Close();    //父进程关闭监听套接字，服务器退出
        }
};